package com.xidian.zhiancloud.service.workTicket;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xidian.zhiancloud.dao.syset.SysUserMapper;
import com.xidian.zhiancloud.dao.syset.usermanage.OrganizationMapper;
import com.xidian.zhiancloud.dao.workTicket.ElectricMapper;
import com.xidian.zhiancloud.dto.ResultDTO;
import com.xidian.zhiancloud.dto.workTicket.ElectricTicketVODTO;
import com.xidian.zhiancloud.enums.GeneralResponseEnums;
import com.xidian.zhiancloud.exception.CustomizeException;
import com.xidian.zhiancloud.model.syset.Organization;
import com.xidian.zhiancloud.model.workTicket.ElectricOperator;
import com.xidian.zhiancloud.model.workTicket.ElectricTicket;
import com.xidian.zhiancloud.qo.workTicket.ElectricTicketQO;
import com.xidian.zhiancloud.util.zyf.RedisUtil;
import com.xidian.zhiancloud.util.zyf.WordUtils;
import com.xidian.zhiancloud.vo.workTicket.ElectricTicketVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.DateFormat;
import java.util.*;

import static com.xidian.zhiancloud.util.zyf.WordUtils.beanToMap;

/**
 * 　　* @program zhiancloud
 * 　　* @author Egoist
 * 　　* @create 2021/5/8 20:41
 *
 */
@Service
public class ElectricService extends ServiceImpl<ElectricMapper, ElectricTicket> implements IService<ElectricTicket> {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Autowired
    private ElectricFlowService electricFlowService;

    @Autowired
    private ElectricMapper electricMapper;

    @Autowired
    private ElectricOperatorService electricOperatorService;

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 自动生成作业票id，公司id + 年 + 月 + 日 + 部门 + 作业票类型 + 4位数字
     *
     * @param CompanyId             公司id
     * @param applicantUnitId       申请单位id
     * @return
     */
    public String createWorkNumber(Long CompanyId, Long applicantUnitId) {
        String workNumber = redisUtil.generateWorkId(CompanyId, applicantUnitId);

        return workNumber;
    }

    public Boolean patchById(ElectricTicket electricTicket) {

        return updateById(electricTicket);
    }

    /**
     * 设置小步骤的isCommit**字段为1，表示已提交
     *
     * @param subStep
     * @param electricTicket
     */
    public ElectricTicket setSubStepFinish(Integer subStep, ElectricTicket electricTicket) {
        switch (subStep) {
            case 1: electricTicket.setIsCommit1(1); break;
            case 2: electricTicket.setIsCommit2(1); break;
            case 3: electricTicket.setIsCommit3(1); break;
            case 4: electricTicket.setIsCommit4(1); break;
            case 5: electricTicket.setIsCommit5(1); break;
            case 6: electricTicket.setIsCommit6(1); break;
            case 7: electricTicket.setIsCommit7(1); break;
            case 8: electricTicket.setIsCommit8(1); break;
            case 9: electricTicket.setIsCommit9(1); break;
            case 10: electricTicket.setIsCommit10(1); break;
            case 11: electricTicket.setIsCommit11(1); break;
            case 12: electricTicket.setIsCommit12(1); break;
            case 13: electricTicket.setIsCommit13(1); break;
        }
        return electricTicket;
    }

    public ElectricTicketVODTO getElectricTicketVODTOById(Long companyId, Long id) {
        ElectricTicketVODTO electricTicketVODTO = new ElectricTicketVODTO();
        // DTO = VO + Map
        ElectricTicketVO electricTicketVO = new ElectricTicketVO();
        ElectricTicket electricTicket = getById(id);
        if (electricTicket == null) {
            throw new CustomizeException(GeneralResponseEnums.GET_FAILED);
        }
        // 将根据id得到的fireTicket字段值，复制到ElectricTicketVO字段中
        BeanUtils.copyProperties(electricTicket, electricTicketVO);
        // 查找-设置部门名称
        Organization organization = organizationMapper.selectById(electricTicket.getApplicantUnitId());
        electricTicketVO.setApplicantUnitName(organization == null ? "该部门不存在" : organization.getName());
        // 根据ticket中的operatorIds查找作业人列表
        String operatorIds = electricTicket.getOperatorIds();
        String[] split = operatorIds.split(",");
        List<ElectricOperator> electricOperatorList = new ArrayList<>();
        for (String s : split) {
            electricOperatorList.add(electricOperatorService.getById(Long.valueOf(s)));
        }
        electricTicketVO.setElectricOperatorList(electricOperatorList);
        electricTicketVO.setRealStartTime(electricTicket.getReviewerSignTime());
        electricTicketVO.setRealFinishTime(electricTicket.getRealEndTime());
        // 获取enableFieldMap
        Integer currentStep = electricTicket.getCurrentStep();
        // 根据大步骤在electric_flow中获取子步骤列表
        List<Long> flowIds = electricFlowService.getSubIdsByCurrent(companyId, currentStep);
        // 根据当前步骤调用函数，返回List<map<人员id,List<可编辑字段>>>
        List<Map<List<Long>, List<String>>> enableField = getEnableFieldMap(companyId, flowIds);

        electricTicketVODTO.setElectricTicketVO(electricTicketVO);
        electricTicketVODTO.setEnableFieldMap(enableField);
        return electricTicketVODTO;
    }

    /**
     * 返回工作流大步骤的{{人员}：{可编辑字段列表}}的映射关系
     *
     * @param flowIds   flow表的id列表，表示最细化的操作
     * @param companyId
     * @return
     */
    public List<Map<List<Long>, List<String>>> getEnableFieldMap(Long companyId, List<Long> flowIds) {
        // 定义返回值
        List<Map<List<Long>, List<String>>> operatorFieldList = new LinkedList<>();
        // 循环subStep.size()，即完成每一个小步骤
        for (Long flowId : flowIds) {
            List<Long> operatorIds = electricFlowService.getOperatorIdsList(flowId, companyId);
            List<String> enableField = electricFlowService.getEnableFieldList(flowId);
            // 新建Hash表，存储人员list与可编辑字段list
            Map<List<Long>, List<String>> operatorFieldMap = new HashMap<List<Long>, List<String>>();
            operatorFieldMap.put(operatorIds, enableField);
            operatorFieldList.add(operatorFieldMap);
        }
        return operatorFieldList;
    }

    /**
     * 根据relateWorkNum，查找对应的t_electric_ticket的id
     *
     * @param relateWorkNum
     * @return
     */
    public Long getRelateTicket(String relateWorkNum, Long companyId) {
        Long relateId = null;
        LambdaQueryWrapper<ElectricTicket> query = Wrappers.<ElectricTicket>lambdaQuery();
        query.eq(ElectricTicket::getCompanyId, companyId).eq(ElectricTicket::getWorkNumber, relateWorkNum);
        List<ElectricTicket> electricTickets = list(query);
        if (electricTickets != null && electricTickets.size() > 0) {
            relateId = electricTickets.get(0).getId();
        }
        return relateId;
    }

    /**
     * 列表查找
     * @param electricTicketQO
     * @return
     */
    public IPage<ElectricTicketVO> getListByQO(ElectricTicketQO electricTicketQO) {
        Page<ElectricTicketVO> electricTicketPage = new Page<>(electricTicketQO.getCurrent(), electricTicketQO.getSize());
        OrderItem orderItem = new OrderItem();
        orderItem.setColumn("create_time").setAsc(false);
        electricTicketPage.getOrders().add(orderItem);
        IPage<ElectricTicketVO> res = electricMapper.getListByQO(electricTicketPage, electricTicketQO);
        return res;
    }

    public ResultDTO<Boolean> approveElectricTicket(ElectricTicket electricTicket) {
        Long ticketId = electricTicket.getId();
        // 前端的fireTicket在根据id更新后端的记录时，不对以下字段做修改
        electricTicket.setUpdateTime(new Date(System.currentTimeMillis()));
        electricTicket.setCompanyId(null);
        electricTicket.setIsCommit1(null);
        electricTicket.setIsCommit2(null);
        electricTicket.setIsCommit3(null);
        electricTicket.setIsCommit4(null);
        electricTicket.setIsCommit5(null);
        electricTicket.setIsCommit6(null);
        electricTicket.setIsCommit7(null);
        electricTicket.setIsCommit8(null);
        electricTicket.setIsCommit9(null);
        electricTicket.setIsCommit10(null);
        electricTicket.setIsCommit11(null);
        electricTicket.setIsCommit12(null);
        // 根据id查询数据库已有数据
        ElectricTicket electricTicketData = getById(ticketId);
        Integer currentStep = electricTicketData.getCurrentStep();

        Date nowTime = new Date(System.currentTimeMillis());
        // 判断该作业票的提交签字已经超时作废
        Date applyTime = electricTicketData.getCreateTime();
        Boolean isOverDate = electricFlowService.signOvertime(applyTime, nowTime);
        if (isOverDate) {
            ElectricTicket wasteTicket = new ElectricTicket();
            wasteTicket.setId(electricTicket.getId());
            wasteTicket.setIsWaste(1);
            updateById(wasteTicket);
            return ResultDTO.errorOf(GeneralResponseEnums.SUBMIT_FAILED);
        }
        //  判断是哪一个小步骤完成了提交
        Integer subStep = electricFlowService.getFinishSubId(currentStep, electricTicket);
        // 将该小步骤步中的isCommit**设置为1，并填充时间
        setSubStepFinish(subStep, electricTicket);

        // 保存
        Boolean res1 = updateById(electricTicket);
        // 获取保存后的ticket
        ElectricTicket newElectricTicket = getById(ticketId);
        // 判断本阶段作业流是否已经结束
        Integer updateStep = electricFlowService.updateCurrentStep(currentStep, newElectricTicket);
        // 更新当前大步骤的状态
        newElectricTicket.setCurrentStep(updateStep);
        //设定是否流程执行完毕
        if (updateStep == 10) {
            newElectricTicket.setIsCommit13(1);
        }
        Boolean res = updateById(newElectricTicket);
        return ResultDTO.successOf(res || res1, GeneralResponseEnums.SUCCESS);
    }

    public ResultDTO<Boolean> export(HttpServletRequest request, HttpServletResponse response, Long ticketId) {
        ElectricTicket electricTicket = getById(ticketId);
        if (electricTicket == null) return ResultDTO.errorOf(-1, "未查找到该数据，导出失败");
        // 由单位id获取申请单位名称
        Organization organization = organizationMapper.selectById(electricTicket.getApplicantUnitId());
        String applicantUnitName = (organization == null ? "该部门不存在" : organization.getName());
        // 时间格式化
        String expectStartTime = getFormatTime(electricTicket.getExpectStartTime());
        String expectEndTime = getFormatTime(electricTicket.getExpectEndTime());
        String realStartTime = getFormatTime(electricTicket.getReviewerSignTime());
        String realEndTime = getFormatTime(electricTicket.getRealEndTime());
        String workDepartmentSignTime = getFormatTime(electricTicket.getWorkDepartmentSignTime());
        String powerDistributionSignTime = getFormatTime(electricTicket.getPowerDistributionSignTime());
        String reviewerSignTime = getFormatTime(electricTicket.getReviewerSignTime());
        String workManagerAcceptanceSignTime = getFormatTime(electricTicket.getWorkManagerAcceptanceSignTime());

        String[] split = electricTicket.getOperatorIds().split(",");
        ElectricOperator operator = electricOperatorService.getById(split[0]);

        Map<String, Object> params = beanToMap(electricTicket);
        // docx的内容
        params.put("applicantUnitName", applicantUnitName);
        params.put("applicantName", electricTicket.getApplicantName());
        params.put("workNumber",electricTicket.getWorkNumber());
        params.put("expectStartTime", expectStartTime);
        params.put("expectEndTime", expectEndTime);
        params.put("realStartTime", realStartTime);
        params.put("realEndTime", realEndTime);

        //作业人
        params.put("workLocation", operator.getWorkLocation());
        params.put("powerAccessPoint", operator.getPowerAccessPoint());
        params.put("operatingVoltage", operator.getOperatingVoltage());
        params.put("equipmentAndPower", operator.getEquipmentAndPower());
        params.put("certificateCode", operator.getCertificateCode());
        params.put("operatorName", operator.getOperatorName());

        //危害辨识
        params.put("operationIdentify", electricTicket.getOperationIdentify());
        params.put("operationSign", electricTicket.getOperationSign());
        params.put("belongPlaceIdentify", electricTicket.getBelongPlaceIdentify());
        params.put("belongPlaceSign", electricTicket.getBelongPlaceSign());
        params.put("powerTransmissionIdentify", electricTicket.getPowerTransmissionIdentify());
        params.put("powerTransmissionSign", electricTicket.getPowerTransmissionSign());

        // 安全措施
        params.put("measure1Sign", electricTicket.getMeasure1Sign());
        params.put("measure2Sign", electricTicket.getMeasure2Sign());
        params.put("measure3Sign", electricTicket.getMeasure3Sign());
        params.put("measure4Sign", electricTicket.getMeasure4Sign());
        params.put("measure5Sign", electricTicket.getMeasure5Sign());
        params.put("measure6Sign", electricTicket.getMeasure6Sign());
        params.put("measure7Sign", electricTicket.getMeasure7Sign());
        params.put("measure8Sign", electricTicket.getMeasure8Sign());
        params.put("measure9Sign", electricTicket.getMeasure9Sign());
        params.put("measure10Sign", electricTicket.getMeasure10Sign());
        params.put("otherMeasure", electricTicket.getOtherMeasure());
        params.put("otherMeasureEditorSign", electricTicket.getOtherMeasureEditorSign());
        params.put("otherMeasureSign", electricTicket.getOtherMeasureSign());

        //意见
        params.put("safeManagerOpinion", electricTicket.getSafeManagerOpinion());
        params.put("safeManagerSign", electricTicket.getSafeManagerSign());

        params.put("workDepartmentOpinion", electricTicket.getWorkDepartmentOpinion());
        params.put("WS", electricTicket.getWorkDepartmentSign());
        params.put("WST", workDepartmentSignTime);

        params.put("powerDistributionOpinion", electricTicket.getPowerDistributionOpinion());
        params.put("DS", electricTicket.getPowerTransmissionSign());
        params.put("DST", powerDistributionSignTime);

        params.put("reviewerOpinion", electricTicket.getReviewerOpinion());
        params.put("RS", electricTicket.getReviewerSign());
        params.put("RST", reviewerSignTime);

        params.put("acceptanceOpinion", electricTicket.getAcceptanceOpinion());
        params.put("AS", electricTicket.getWorkManagerAcceptanceSign());
        params.put("AST",workManagerAcceptanceSignTime);

        String path = "workTicket/临时用电票.doc";
        ClassPathResource cpr = new ClassPathResource(path);
        System.out.println(cpr.getPath());
        //这里是我说的一行代码
        //"/Users/zhangyifan/IdeaProjects/zhiancloud/src/main/resources/workTicket/export.docx"
        String fileName = UUID.randomUUID().toString() + ".docx";
        WordUtils.exportWord(cpr.getPath(), fileName, params, request, response);
        WordUtils.delFileWord(fileName);
        return ResultDTO.successOf(true, GeneralResponseEnums.SUCCESS);
    }

    /**
     * 获取中文的格式化时间
     *
     * @param originalTime
     * @return
     */
    public String getFormatTime(Date originalTime) {
        // 获取不同格式化风格和中国环境的日期
        DateFormat transTime = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.CHINA);
        // 将不同格式化风格的时间格式化为时间字符串
        String time = transTime.format(originalTime);
        return time;
    }

    /**
     * 返回字符串分割
     *
     * @param originalStr
     * @return
     */
    public List<String> getSplitList(String originalStr) {
        List<String> riskList = new LinkedList<>();
        if (originalStr != null) {
            for(String original : originalStr.split(",")) {
                riskList.add(original);
            }
        }
        return riskList;
    }
}
